package com.mmd.base.utils;

import cn.hutool.extra.spring.SpringUtil;
import com.mmd.core.enums.ResultEnum;
import com.mmd.core.enums.SmsEnum;
import com.mmd.core.utils.RandomUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * 验证码存储验证 工具类
 */
public class CodeUtils {

    /**
     * 验证码过期时间
     */
    private static final long codeTimeOut = 60 * 5;

    /**
     * 验证码长度
     */
    private static final int length = 5;

    /**
     * 获取字符串redis模板
     */
    private static StringRedisTemplate redisTemplate = SpringUtil.getBean(StringRedisTemplate.class);

    /**
     * 获取string value redis操作实例
     */
    public static ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

    /**
     * 设置验证码
     * @param phone 接收短信手机号
     * @return 验证码
     */
    public static String setCode(SmsEnum smsEnum, String phone)
    {
        return setCode(smsEnum,phone,length,codeTimeOut);
    }

    /**
     * 设置验证码
     * @param phone 接收短信手机号
     * @param codeTimeOut 验证码过期时间 单位S
     * @return 验证码
     */
    public static String setCode(SmsEnum smsEnum, String phone, long codeTimeOut)
    {
        return setCode(smsEnum,phone,length,codeTimeOut);
    }

    /**
     * 设置验证码
     * @param phone 接收短信手机号
     * @param length 验证码长度
     * @return 验证码
     */
    public static String setCode(SmsEnum smsEnum, String phone, Integer length)
    {
        return setCode(smsEnum,phone,length,codeTimeOut);
    }

    /**
     * 设置验证码
     * @param phone 接收短信手机号
     * @param length 验证码长度
     * @param codeTimeOut 过期时间 单位S
     * @return 验证码
     */
    public static String setCode(SmsEnum smsEnum, String phone, Integer length, long codeTimeOut)
    {
        Assert.isTrue(!Optional.ofNullable(valueOperations.get(smsEnum.getKey() + phone)).isPresent(), ResultEnum.FAIL_REQUEST_REPETITION.getMessage());
        redisTemplate.delete(smsEnum.getKey() + phone);
        String rawCode = "";
        String code = "";
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        rawCode = code = RandomUtils.randAnd0_9(length);
        code = passwordEncoder.encode(code);
        valueOperations.set(smsEnum.getKey()+phone,code,codeTimeOut, TimeUnit.SECONDS);
        return rawCode;
    }

    /**
     * 验证验证码
     * @param phone 接收短信手机号
     * @param code 验证码
     */
    public static void validCode(SmsEnum smsEnum, String phone, String code)
    {
        String rawCode = valueOperations.get(smsEnum.getKey() + phone);
        Assert.isTrue(!StringUtils.isEmpty(rawCode), ResultEnum.FAIL_CODE_PARAM.getMessage());
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        Assert.isTrue(passwordEncoder.matches(code,rawCode), ResultEnum.FAIL_CODE_PARAM.getMessage());
        redisTemplate.delete(smsEnum.getKey() + phone);
    }
}
